﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace FluentStateObserver.Test
{

    /// <summary>
    /// A Mock Observable for testing.  Add Blocks, then call ProcessBlocks to begin the publishing.
    /// </summary>
    public class TestObservable : IObservable<TestElement>
    {
        /// <summary>
        /// The observers to publish to.
        /// </summary>
        private List<IObserver<TestElement>> Observers = new List<IObserver<TestElement>>();

        /// <summary>
        /// The blocks that specify the series of elements to publish.
        /// </summary>
        private List<GenericObservableBlock<TestElement>> Blocks = new List<GenericObservableBlock<TestElement>>();


        /// <summary>
        /// Adds the block to the series.
        /// </summary>
        /// <param name="block">The block to add.</param>
        public void AddBlock(GenericObservableBlock<TestElement> block)
        {
            Blocks.Add(block);
        }

        /// <summary>
        /// Processes the blocks. Publishing the Elements.
        /// </summary>
        public void ProcessBlocks()
        {
            foreach (var block in Blocks)
            {
                foreach (var obs in Observers)
                {
                    obs.OnNext(block.Element);
                }

                // Sleep for the wait seconds.
                Thread.Sleep(TimeSpan.FromSeconds(block.WaitSeconds));
            }
        }

        #region IObservable<TestElement> Members

        /// <summary>
        /// Subscribes an observer to the observable sequence.
        /// </summary>
        /// <param name="observer">The observer to subcribe</param>
        /// <returns>A Disposable object to free up resources on completion.</returns>
        public IDisposable Subscribe(IObserver<TestElement> observer)
        {
            Observers.Add(observer);

            return new AnonymousDisposable(() => Observers.Remove(observer));
        }

        #endregion
    }
}
